#include "StepByStep.h"

#define DISPLAYTYPE1

void PrintValueList(ValueList *VL)
{
  VList *Pt;

  if (VL->NumValue != 1) fprintf(Output, "{");

  for (Pt = VL->List; Pt != NULL; Pt = Pt->next)
    fprintf(Output, "%s%s", GetObjectName(Pt->Idx), (Pt->next!=NULL ? "," : ""));
//  fprintf(Output, "%d%s", Pt->Idx, (Pt->next!=NULL ? "," : ""));

  if (VL->NumValue != 1) fprintf(Output, "}");

//fprintf(Output, "/%d", VL->ParaIdx);
}

void PrintTokenList(Bool Head, TokenList *Pt)
{
  fprintf(Output, "(");
  if (Head) {
    fprintf(Output, "%s%s", NameOfPred(Pt->VList.ParaIdx), (Pt->next!=NULL?" ":""));
    Pt = Pt->next;
  }

  while (Pt != NULL) {
    PrintValueList(&(Pt->VList));
    fprintf(Output, "%s", (Pt->next!=NULL?" ":""));
    Pt = Pt->next;
  }
  fprintf(Output, ")");
}

#ifdef DISPLAYTYPE
void PrintTypeList(StringList *Pt)
{
  fprintf(Output, "-[");
  while (Pt != NULL) {
    fprintf(Output, "%s%s", Pt->Name, (Pt->next!=NULL?",":""));
    Pt = Pt->next;
  }
  fprintf(Output, "]");
}
#endif

void PrintTypedArray(char *Msg, int Num, TypedList *Para)
{
  int i;

  fprintf(Output, "(%s", Msg);
  for (i = 0; i < Num; i++,Para++) {
    fprintf(Output, " ");
    if (Para->VList.NumValue != 0) PrintValueList(&(Para->VList));
    else fprintf(Output, "%s/%d", Para->VList.Name,Para->VList.ParaIdx);

#ifdef DISPLAYTYPE
    if (Typing) PrintTypeList(Para->Type);
#endif
  }
  fprintf(Output, ")");
}

void PrintLawPred(DomainLaw *law, int Part)
{
  TypeOfNode Not;
  TokenList  *Pt;

  if (Part == HEADOFLAW) { Not = law->Not1;  Pt = law->Pred1; }
  else { Not = law->Not2;  Pt = law->Pred2; }

  fprintf(Output, "%s(%s", (Not==NOT ? "(not ":""), NameOfPred(Pt->VList.ParaIdx));
  for (Pt = Pt->next; Pt != NULL; Pt = Pt->next)
    if (Pt->VList.NumValue > 0) fprintf(Output, " %s", GetObjectName(Pt->VList.List->Idx));
    else fprintf(Output, " %s", (law->Para+Pt->VList.ParaIdx)->VList.Name);

  fprintf(Output, ")%s", (Not ? ")" : ""));
}

void PrintPCListOfLaw(TypedList *Para, PCOfLaw *PC)
{
  TokenList *Pt;

#ifdef TEST
  fprintf(Output, "\t\t{");
#else
  fprintf(Output, "\t{");
#endif

  while (PC != NULL) {
    Pt = PC->Pred;
    fprintf(Output, "%s(%s", (PC->Not ? "(not " : ""), Pt->VList.Name);
    for (Pt = Pt->next; Pt != NULL; Pt = Pt->next)
      if (IsConstant(Pt->VList.ParaIdx)) fprintf(Output, " %s", GetObjectName(Pt->VList.List->Idx));
      else fprintf(Output, " %s", (Para+Pt->VList.ParaIdx)->VList.Name);

    fprintf(Output, ")%s", (PC->Not ? ")" : ""));

    PC = PC->next;
    if (PC != NULL) fprintf(Output, ", ");
  }

  fprintf(Output, "}\n");
}

void PrintOneDomainLaw(DomainLaw *law)
{
  char Msg[5];
  int  i;

#ifdef TEST
  fprintf(Output, "%03d(%02d, %02d) ", law->Index, law->Idx1, law->Idx2);
#endif

  if (law->Flag < LAW1) fprintf(Output, "M:%d\t", law->Mutex);
  else fprintf(Output, "S:%d\t", law->Step);

  PrintTypedArray("", law->NumPara, law->Para);
  fprintf(Output, "\n");

  if (law->PCLaw != NULL) PrintPCListOfLaw(law->Para, law->PCLaw);

  i = 0;
  Msg[i++] = ((law->Flag==LAW01 || law->Flag==LAW3) ? '=' : '-');
  if (law->Flag > LAW01) Msg[i++] = '\\';
  if (law->Flag > LAW1) Msg[i++] = '\\';
  Msg[i++] = Msg[0];
  Msg[i] = 0;

  fprintf(Output, "\t\t");
  PrintLawPred(law, HEADOFLAW);
  fprintf(Output, " %s> ", Msg);
  PrintLawPred(law, TAILOFLAW);
  fprintf(Output, "\n");

  if (law->PC != NULL) PrintPCListOfLaw(law->Para, law->PC);
}

void PrintLawsOfDomain(char *Msg, int Num, DomainLaw *laws)
{
  DomainLaw *law;
  int       i;

  fprintf(Output, "%s Laws: %d\n", Msg, Num);

  for (i = 0; i < NumPred; i++)
    for (law = (laws+i)->next; law != NULL; law = law->next)
      PrintOneDomainLaw(law);

  fprintf(Output, "\n");
}

#ifdef DISPLAYTREE
void PrintFactInformation()
{
  TypedList *Pt;
  PENode    *PE;
  int       i;

  fprintf(Output, "Problem: %s\nDomain: %s\n", ProbName, DomName);

  fprintf(Output, "Objects:");
  Pt = Objects;
  for (i = 0; i < NumObject; i++,Pt++) {
    fprintf(Output, "%s\t%02d - %s", (i%2==0?"\n":""), i, Pt->VList.Name);
#ifdef DISPLAYTYPE
    if (Typing) PrintTypeList(Pt->Type);
#endif
  }

  fprintf(Output, "\nInit:");
  for (PE = Init; PE != NULL; PE = PE->next) {
    fprintf(Output, "\n\t%s", (PE->Type==NOT ? "not " : ""));
    PrintTokenList(TRUE, PE->Pred);
  }

  fprintf(Output, "\nGoal:");
  for (PE = Goal; PE != NULL; PE = PE->next) {
    fprintf(Output, "\n\t%s", (PE->Type==NOT ? "not " : ""));
    PrintTokenList(TRUE, PE->Pred);
  }

  fprintf(Output, "\nThe definition of problem finished\n\n");
}

void PrintTypedList(TypedList *Pt)
{
  int i;

  for (i = 0; Pt != NULL; i++,Pt=Pt->next) {
    fprintf(Output, "\n\t(%s", Pt->VList.Name);

#ifdef DISPLAYTYPE
    if (Typing) PrintTypeList(Pt->Type);
#endif
    fprintf(Output, ")");
  }
}

void PrintAxiomPart(PENode *PE)
{
  while (PE != NULL) {
    fprintf(Output, "%s ", Types[PE->Type]);
    switch (PE->Type) {
      case ATOM:
      case NOT:
           PrintTokenList(TRUE, PE->Pred);
           break;
/*    case AND:
      case OR:
           fprintf(Output, "(");
           PrintAxiomPart(PE->sons);
           fprintf(Output, ")");
           break;*/
      case WHEN: case EXIST: case FORALL:
           fprintf(Output, "The Axiom of domain is error\n");
           exit(ERROR);
/*    case FORALL:
           fprintf(Output, "\t");
           PrintTypedList(pt->vars);
           PrintAxiomPart(Level+1, pt->sons);
           break;*/
      default:
           fprintf(Output, "Invalid Type of Effect\n");
           break;
    }

    PE = PE->next;
    if (PE != NULL) fprintf(Output, ", ");
  }
}

void PrintPENodeValueList(char *Msg, PENode *PE)
{
  PENode *PE1;

  fprintf(Output, "\n%s:", Msg);

  for (; PE != NULL; PE = PE->next)
    switch (PE->Type) {
      case ATOM:
      case NOT:
           PrintOnePred(1, PE);
           break;
      case OR:
           fprintf(Output, "\n\tOR (");
           for (PE1 = PE->sons; PE1 != NULL; PE1 = PE1->next)
             PrintOnePred(1, PE1);

           fprintf(Output, "\n\t)");
           break;
      case WHEN:
           fprintf(Output, "\n  When:");
           for (PE1 = PE->sons; PE1 != NULL; PE1 = PE1->next)
             PrintOnePred(2, PE1);

           fprintf(Output, "\n    Effect:");
           for (PE1 = PE->Effect; PE1 != NULL; PE1 = PE1->next)
             PrintOnePred(4, PE1);
           break;
      default:
           fprintf(Output, "The PC/Effect of action is error\n");
           exit(ERROR);
    }
}

void PrintDomain()
{
  DomainAxiom *Pt;
  ActionList  *Act;
  SafetyStru  *Pt4;
  StringList  *Pt1;
  TypedList   *Pt2;
  PredList    *Pt3;
  PENode      *PE;
  char        SPred[5] = "SADC";
  int         i;

  fprintf(Output, "Domain: %s", Name);

  fprintf(Output, "\nRequirement:");
  for (i=0,Pt1=Require; Pt1 != NULL; i++,Pt1=Pt1->next)
    fprintf(Output, "\n\t%s", Pt1->Name);

  fprintf(Output, "\nTypes:");  PrintTypedList(Type);

  fprintf(Output, "\nConstants:");
  for (i=0,Pt2=Constants; i < NumConstant; i++,Pt2++) {
    fprintf(Output, "%s\t%02d - %s", (i%3==0?"\n":""), i, Pt2->VList.Name);
#ifdef DISPLAYTYPE
    if (Typing) PrintTypeList(Pt2->Type);
#endif
  }

  fprintf(Output, "\nSafety:");
  for (i=0,Pt4=Safe; Pt4 != NULL; Pt4 = Pt4->next) {
    fprintf(Output, "\n%d:", i++);
    PrintTypedArray("", Pt4->NumPara, Pt4->Vars);

    for (PE = Pt4->sons; PE != NULL; PE = PE->next)
      PrintOnePred(7, PE);
  }

  fprintf(Output, "\nPredicates:");
  for (i=0,Pt3=Predication; i<NumPred; i++,Pt3++) {
    fprintf(Output, "\n\t%02d - ", i);
    PrintTypedArray(Pt3->Name, Pt3->NumPara, Pt3->Para);
    fprintf(Output, "\t%c A:%d E:%d S:%d", SPred[Pt3->Class], Pt3->Axiom, Pt3->Exclude, Pt3->Safety);
  }

  for (Pt = Axioms; Pt != NULL; Pt = Pt->next) {
    fprintf(Output, "\n\nAxiom: %s\n    ", Pt->Name);
    PrintTypedArray("Vars: ", Pt->NumPara, Pt->Vars);
    fprintf(Output, "\n    Context: ");  PrintAxiomPart(Pt->Context);
    fprintf(Output, "\n    Imply: ");    PrintAxiomPart(Pt->Imply);
  }

  fprintf(Output, "\n\nActions:");
  for (i = 0; i < NumAct; i++) {
    Act = (Action+i)->next;
    fprintf(Output, "\n%02d - ", i);

    PrintTypedArray(Act->Name, Act->NumPara, Act->Para);
    fprintf(Output, " PC:%d Type:%d", Act->NumPC, Act->Type);

    PrintPENodeValueList(" PC", Act->PC);
    PrintPENodeValueList(" Effect", Act->Effect);
#ifdef WHEN_CLAUSE
    if (IsType(Act->Type, WHEN)) PrintPENodeValueList(" CondEffect", Act->CondEffect);
#endif
    fprintf(Output, "\n");
  }

  fprintf(Output, "\n<< The definition of domain finished >>\n\n");
}

void PrintPKTree(PKTree *Pk)
{
  PredKnowledge *PC;
  int           j;

  if (Pk->PC != NULL) fprintf(Output, "\n");
  for (PC = Pk->PC; PC != NULL; PC = PC->next) {
    j = PC->PredNo;
    fprintf(Output, "%s", (PC->Type==NOT ? "(not ":""));
    PrintTypedArray(NameOfPred(j), NumParaOfPred(j), PC->Para);
    if (PC->next != NULL) fprintf(Output, ", ");
  }

  PrintPredication(1, Pk->Pred);  fprintf(Output, "\n");
}

void PrintKnowledgeTree()
{
  PKTree *Pk, *Pk1, *Pk2;
  int    i;

  Pk1 = PK;   Pk2 = nPK;
  for (i = 0; i < NumPred; i++,Pk1++,Pk2++) {
    if (Pk1->next==NULL && Pk2->next==NULL) continue;

    fprintf(Output, "%02d -- Predication", i);

    if (Pk1->next == NULL) fprintf(Output, "\n %s\n", NameOfPred(i));
    for (Pk = Pk1->next; Pk != NULL; Pk = Pk->next)
      PrintPKTree(Pk);

    if (Pk2->next == NULL) fprintf(Output, "\n Not %s\n", NameOfPred(i));
    for (Pk = Pk2->next; Pk != NULL; Pk = Pk->next)
      PrintPKTree(Pk);

    fprintf(Output, "\n");
  }

  fprintf(Output, "<< Knowledge trees finished >>\n\n");
}

void PrintDomainLawList(DomainLaw *law, char *Msg)
{
  fprintf(Output, "%s Law:\n", Msg);
  for ( ; law != NULL; law = law->next) PrintOneDomainLaw(law);
  fprintf(Output, "\n");
}

void PrintMessageWithLeftMargin(int Level, char *Msg)
{
  char *String;
  int  Len;

  Len = Level << 1;
  String = (char *) calloc(Len+1, sizeof(char));
  memset(String, ' ', Len);
  fprintf(Output, "\n%s%s", String, Msg);
  free(String);
}

void PrintOnePred(int Level, PENode *PE)
{
  TokenList *Pt;

  PrintMessageWithLeftMargin(Level, (PE->Type==NOT ? " not ":" "));

  Pt = PE->Pred;
  fprintf(Output, "(%s", Pt->VList.Name);
  for (Pt = Pt->next; Pt != NULL; Pt = Pt->next) {
    fprintf(Output, " ");
    PrintValueList(&(Pt->VList));
  }
  fprintf(Output, ")");
}

void PrintListOfEffect(char *Msg, int Level, PENode *PE)
{
  PrintMessageWithLeftMargin(Level, Msg);

  Level++;
  if (PE == NULL) PrintMessageWithLeftMargin(Level, " <Empty>");
  else while (PE != NULL) {
         PrintOnePred(Level, PE);
         if (PE->Delete) fprintf(Output, " Deleted");
         PE = PE->next;
       }
}

void PrintActKnowledge(int Height, ActKnowledge *ActK)
{
  PredKnowledge *PC;
  int           ActNo, Level;

  Level = ActK->Parent->Level + 1;

  ActNo = ActK->ActNo;
  PrintTypedArray(ACTIONNAME(ActNo), NumParaOfAct(ActNo), ActK->Para);
//fprintf(Output, ") H:%d A:%d", ActK->Height, ActK->Acts);

  if (ActK->UComplete) fprintf(Output, " U");

  if (ActK->PC != NULL) PrintMessageWithLeftMargin(Level, " PC:");
  for (PC = ActK->PC; PC != NULL; PC = PC->next)
    PrintPredication(Height, PC);

  if (ActK->Effect != NULL) PrintListOfEffect(" Effect:", Level, ActK->Effect);

#ifdef WHEN_CLAUSE
  if (IsType(ActK->Type, WHEN)) {
     PENode *PE;

     PrintMessageWithLeftMargin(Level, " CondEffect:");
     for (PE = ActK->CondEffect; PE != NULL; PE = PE->next) {
       PrintListOfEffect("When:", Level+1, PE->sons);
       PrintListOfEffect("Effect:", Level+3, PE->Effect);
     }
  }
#endif
}

void PrintOnePredication(PredKnowledge *Pd)
{
  PrintMessageWithLeftMargin(Pd->Level, "");

  fprintf(Output, " %d:%s", Pd->Index, (Pd->Type==NOT ? "not ":""));
  PrintTypedArray(NameOfPred(Pd->PredNo), NumParaOfPred(Pd->PredNo)+Pd->NumEP, Pd->Para);
  fprintf(Output, " F:%d S:%d C:%d N:%d",
                  Pd->Fact, ClassOfPred(Pd->PredNo), Pd->Character, Pd->NumNonValue);
//fprintf(Output, "\t%c", State[PREDSTATE(Pd->PredNo)]);
//   fprintf(Output, " F:%d H:%d L:%d A:%d NA:%d",
//                   Pd->Fact, Pd->Height, Pd->Level, Pd->Acts, Pd->NumAct);
}

void PrintPredication(int Height, PredKnowledge *Pd)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  int           i, Level;

  PrintOnePredication(Pd);

  if (Pd->CPC != NULL) {
     PrintMessageWithLeftMargin(Pd->Level+1, " C-PC:");
     for (PC = Pd->CPC; PC != NULL; PC = PC->next)
       PrintOnePredication(PC);
  }

  if (Pd->CEffect != NULL) PrintListOfEffect(" C-Effect:", Pd->Level+1, Pd->CEffect);

  if (Height>0 && Pd->Height != FINISHED) {
     if (Pd->UComplete)
     fprintf(Output, " U");
     for (i=1,ActK=Pd->Act; ActK != NULL; ActK = ActK->next)
//     if (IsValid(Pd, ActK))
       {
          Level = ActK->Parent->Level + 1;
          PrintMessageWithLeftMargin(Level, " ");
          fprintf(Output, "%d.%d-%d ", Level, ActK->Index, i++);
          PrintActKnowledge(Height-1, ActK);
       }
  }
}

void PrintPlanTreeLeaf(char *Msg, ReadyTreeLeaf *PT)
{
  PredKnowledge *Pd;
  int           i;

  fprintf(Output, "%s Targets:", Msg);
  for (i = 1; PT != NULL; i++,PT=PT->next) {
    fprintf(Output, "\n%02d R:%d TIndex:%d Index:%d L:%d, ",
                     i, PT->Ready, PT->TIndex, PT->Index, PT->Pred->Level);

    Pd = PT->Pred;
    fprintf(Output, " %s", (Pd->Type==NOT ? "not ":""));
    PrintTypedArray(NameOfPred(Pd->PredNo), NumParaOfPred(Pd->PredNo)+Pd->NumEP, Pd->Para);
    PrintPredication(2, PT->Pred); fprintf(Output, "\n");
  }
  fprintf(Output, "\n\n");
}

void PrintInfoOfPlanningState(char *Msg)
{
  PredFact *Pt;
  int      i, j;

  fprintf(Output,"\n<< %s State >>", Msg);
  for (i = 0; i < NumPred; i++)
    if (!IsClass(i, STATIC)) {
       fprintf(Output,"\n[%d]:%02d/%02d -- %s", i, State[i].Left, State[i].Total, NameOfPred(i));
       Pt = State[i].List;
       if (Pt == NULL) fprintf(Output,"\n\t<Empty>");
       else for (j = 0; Pt != NULL; j++,Pt=Pt->next) {
              fprintf(Output,"\n\tFinish:%d - ", Pt->Finish);
              PrintTokenList(FALSE, Pt->Para);
            }
    }
  fprintf(Output,"\n<< End of State >>\n");
}

// Print all Actions in the Plan
void PrintPlanList()
{
  PredKnowledge *Pd;
  ActKnowledge  *ActK;
  PlanList      *PL;
  int           i;

  fprintf(Output, "\n<< List of Plan >>");
  for (PL = Plan; PL != NULL; PL = PL->next) {
    Pd = PL->Pred;

    fprintf(Output, "\n%03d - %s", PL->Step, (Pd->Type==NOT ? "not " : ""));
    PrintTypedArray(NameOfPred(Pd->PredNo), NumParaOfPred(Pd->PredNo), Pd->Para);
    for (i=1,ActK=Pd->Act; ActK != NULL; i++,ActK=ActK->next) {
      fprintf(Output, "\n     %02d. ", i);
      PrintTypedArray(ACTIONNAME1(ActK->ActNo), NumParaOfAct(ActK->ActNo), ActK->Para);
    }
    if (Pd->NumAct > 1 || Pd->CEffect!=NULL || Pd->Act->Effect!=NULL)
       PrintPredication(12, Pd);
  }
  fprintf(Output, "\n<< End of Plan >>\n");

  PrintInfoOfPlanningState("Inter-Mediate");
}

void PrintLelationOfTarget(char *Msg)
{
  Bool *Pt;
  int  i, j;

  fprintf(Output, "\nR Of Target: %s\n    ", Msg);

  for (i = 0; i < NumTarget; i++) fprintf(Output, "%2d", i);

  for (i = 0; i < NumTarget; i++) {
    fprintf(Output, "\n%2d:", i);
    Pt = RT[i].R;
    for (j = 0; j < NumTarget; j++,Pt++) fprintf(Output, "%2d", *Pt);
  }
  fprintf(Output, "\n");
}

void PrintValueListOfPC(int idx, ValueListOfPC *PL)
{
  PCParaLink *PL1;

  fprintf(Output, "%d: %d\n", idx, PL[idx].Status);
  for (PL1 = PL[idx].List; PL1 != NULL; PL1 = PL1->next) {
    PrintTokenList(FALSE, PL1->Para);
    fprintf(Output, " F:%d\n", PL1->Fact);
  }
}
#endif
